package com.aviatorscript.avitorscriptmust.aspect;

import com.aviatorscript.avitorscriptmust.annotation.AviatorValidation;
import com.aviatorscript.avitorscriptmust.dto.ValidationResult;
import com.aviatorscript.avitorscriptmust.validation.AviatorValidationExecutor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;

/**
 * AviatorScript校验切面
 * 拦截带有@AviatorValidation注解的方法，自动执行参数校验
 *
 * @author system
 */
@Aspect
@Component
@Slf4j
public class ValidationAspect {
    
    @Autowired
    private AviatorValidationExecutor validationExecutor;
    
    /**
     * 环绕通知：拦截带有@AviatorValidation注解的方法
     */
    @Around("@annotation(com.aviatorscript.avitorscriptmust.annotation.AviatorValidation) || " +
            "execution(* *(.., @com.aviatorscript.avitorscriptmust.annotation.AviatorValidation (*), ..))")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        Object[] args = joinPoint.getArgs();
        
        // 检查方法是否有@AviatorValidation注解
        AviatorValidation methodAnnotation = method.getAnnotation(AviatorValidation.class);
        if (methodAnnotation != null && !methodAnnotation.enabled()) {
            // 如果方法级别的注解禁用了校验，直接执行方法
            return joinPoint.proceed();
        }
        
        // 校验所有带有@AviatorValidation注解的参数
        Parameter[] parameters = method.getParameters();
        Annotation[][] parameterAnnotations = method.getParameterAnnotations();
        
        for (int i = 0; i < parameters.length; i++) {
            Object arg = args[i];
            if (arg == null) {
                continue; // 跳过null参数
            }
            
            // 检查参数是否有@AviatorValidation注解
            AviatorValidation paramAnnotation = findAviatorValidationAnnotation(parameterAnnotations[i]);
            if (paramAnnotation != null) {
                validateParameter(arg, paramAnnotation, method.getName(), i);
            }
            
            // 如果方法级别启用了校验，也校验所有参数（除非参数显式禁用）
            if (methodAnnotation != null && (paramAnnotation == null || paramAnnotation.enabled())) {
                validateParameter(arg, methodAnnotation, method.getName(), i);
            }
        }
        
        // 所有校验通过，执行原方法
        return joinPoint.proceed();
    }
    
    /**
     * 查找参数上的@AviatorValidation注解
     */
    private AviatorValidation findAviatorValidationAnnotation(Annotation[] annotations) {
        for (Annotation annotation : annotations) {
            if (annotation instanceof AviatorValidation) {
                return (AviatorValidation) annotation;
            }
        }
        return null;
    }
    
    /**
     * 校验单个参数
     */
    private void validateParameter(Object parameter, AviatorValidation annotation, 
                                 String methodName, int paramIndex) {
        if (!annotation.enabled()) {
            return; // 校验被禁用
        }
        
        try {
            // 确定要校验的类名
            String className = annotation.className();
            if (!StringUtils.hasText(className)) {
                className = parameter.getClass().getSimpleName();
            }
            
            log.debug("开始校验参数: method={}, paramIndex={}, className={}", 
                     methodName, paramIndex, className);
            
            // 执行校验
            ValidationResult result = validationExecutor.validate(parameter);
            
            if (!result.isValid()) {
                String errorMessage = String.format("%s: %s", 
                    annotation.message(), result.getErrorMessage());
                
                log.warn("参数校验失败: method={}, paramIndex={}, errors={}", 
                        methodName, paramIndex, result.getErrorMessages());
                
                if (annotation.throwException()) {
                    throw new IllegalArgumentException(errorMessage);
                }
            } else {
                log.debug("参数校验通过: method={}, paramIndex={}, className={}, elapsedTime={}ms", 
                         methodName, paramIndex, className, result.getElapsedTime());
            }
            
        } catch (IllegalArgumentException e) {
            // 重新抛出校验异常
            throw e;
        } catch (Exception e) {
            log.error("校验过程发生异常: method={}, paramIndex={}, error={}", 
                     methodName, paramIndex, e.getMessage(), e);
            
            if (annotation.throwException()) {
                throw new RuntimeException("校验过程发生异常: " + e.getMessage(), e);
            }
        }
    }
} 